from typing import Annotated, Optional

from fastapi import Query, Body
from pydantic import model_validator

from app.utils import types
from app.models.common import AppId, Pagination, FirewallRuleId
from app.models import responses


class AppFirewallRuleList(AppId, Pagination):
    """分页获取指定应用的防火墙列表"""
    rule_type: Optional[int]
    rule_match: str
    remark: str
    is_enabled: Optional[bool]

    @model_validator(mode='before')
    @classmethod
    def before(cls, data):
        data = types.safe_dict(data)
        data['rule_type'] = types.safe_int(data.get('rule_type', None), None)
        data['rule_match'] = data.get('rule_match', '')
        data['remark'] = data.get('remark', '')
        data['is_enabled'] = data.get('is_enabled', None)
        return data

    @model_validator(mode='after')
    def after(self):
        if self.rule_type is not None and not (0 <= self.rule_type <= 255):
            raise responses.FailureResponseError(-102, msg='规则的限制类型应介于 0-255 之间')

        if len(self.rule_match) > 256:
            raise responses.FailureResponseError(-102, msg='规则的限制匹配内容不能超过 256 位')

        if len(self.remark) > 512:
            raise responses.FailureResponseError(-102, msg='规则的备注长度不能超过 512 位')

        return self


AppFirewallRuleListParams = Annotated[AppFirewallRuleList, Query()]


class CreateFirewallRule(AppId):
    """创建防火墙规则"""
    rule_type: Optional[int]
    rule_match: str
    is_enabled: bool
    remark: str

    @model_validator(mode='before')
    @classmethod
    def before(cls, data):
        data = types.safe_dict(data)
        data['rule_type'] = types.safe_int(data.get('rule_type', ''), None)
        data['rule_match'] = data.get('rule_match', '')
        data['is_enabled'] = data.get('is_enabled', True)
        data['remark'] = data.get('remark', '')
        return data

    @model_validator(mode='after')
    def after(self):
        if self.rule_type is None:
            raise responses.FailureResponseError(-102, msg='请输入有效的限制类型')

        if self.rule_type is not None and not (0 <= self.rule_type <= 255):
            raise responses.FailureResponseError(-102, msg='规则的限制类型应介于 0-255 之间')

        if not (4 <= len(self.rule_match) <= 128):
            raise responses.FailureResponseError(-102, msg='规则的限制匹配内容长度范围为：4-128')

        return self


CreateFirewallRuleJSON = Annotated[CreateFirewallRule, Body()]


class EnableFirewallRule(FirewallRuleId):
    """是否启用某条规则"""
    is_enabled: bool = True


EnableFirewallRuleJSON = Annotated[EnableFirewallRule, Body()]


class BatchAppRuleIds(AppId):
    rule_ids: list[int] = []

    @model_validator(mode='before')
    @classmethod
    def before(cls, data):
        data = types.safe_dict(data)
        rule_ids = []
        for raw_rule_id in list(data.get('rule_ids', [])):
            rule_id = types.safe_int(raw_rule_id, None)
            if rule_id is not None:
                rule_ids.append(rule_id)

        data['rule_ids'] = rule_ids
        return data

    @model_validator(mode='after')
    def after(self):
        if type(self.rule_ids) is not list:
            raise responses.FailureResponseError(-102, msg='多个规则 ID 必须是列表类型')

        if len(self.rule_ids) == 0:
            raise responses.FailureResponseError(-102, msg='请传入至少 1 个规则 ID')

        return self


BatchDeleteAppRulesJSON = Annotated[BatchAppRuleIds, Body()]
